#include "smart_net_pair.hpp"

int SmartNetPair::init_server()
{
    int ret;
    uint32_t buff_max_size = 16 * 1024 * 1024;

    m_sockFd = nn_socket(AF_SP, NN_PAIR);
        if (m_sockFd < 0) {
        LOG_ERROR("nn_socket: %s\n", nn_strerror (nn_errno ()));
        exit(EXIT_FAILURE);
    }

    ret = nn_setsockopt (m_sockFd, NN_SOL_SOCKET, NN_RCVMAXSIZE, &buff_max_size, sizeof(buff_max_size));
    if (ret < 0) {
        LOG_ERROR("set NN_RCVMAXSIZE: %s\n", nn_strerror (nn_errno ()));
        nn_close (m_sockFd);
        exit(EXIT_FAILURE);        
    }

    ret = nn_bind(m_sockFd, m_sockUrl.c_str());
        if (ret < 0) {
        LOG_ERROR("nn_bind: %s\n", nn_strerror (nn_errno ()));
        nn_close (m_sockFd);
        exit(EXIT_FAILURE);
    }

    return ret;
}

int SmartNetPair::init_client()
{
    int ret;

    m_sockFd = nn_socket(AF_SP, NN_PAIR);
    if (m_sockFd < 0) {
        LOG_ERROR("nn_socket: %s\n", nn_strerror (nn_errno ()));
        exit(EXIT_FAILURE);
    }

    {
        int buff_max_size = 16*1024*1024;
        int ret = nn_setsockopt (m_sockFd, NN_SOL_SOCKET, NN_RCVMAXSIZE, &buff_max_size, sizeof(buff_max_size));
        if (ret < 0) {
            LOG_ERROR("set NN_RCVMAXSIZE: %s\n", nn_strerror (nn_errno ()));
            nn_close (m_sockFd);
            exit(EXIT_FAILURE);      
        }
    }

    ret = nn_connect(m_sockFd, m_sockUrl.c_str());
    if (ret < 0) {
        LOG_ERROR("nn_connect: %s\n", nn_strerror (nn_errno ()));
        nn_close (m_sockFd);
        exit(EXIT_FAILURE);
    }

    return 0;
}


int SmartNetPair::deinit()
{
    if (m_sockFd >= 0) {
        nn_shutdown(m_sockFd, 0);
    }
    return 0;
}


int SmartNetPair::send_mesg(uint8_t *data, uint32_t len)
{
    int ret;

    ret = nn_send(m_sockFd, data, len, 0);
    if (ret < 0) {
        LOG_ERROR("nn_send: %s (ignoring)\n", nn_strerror (nn_errno ()));
    }

    return ret;
}


int SmartNetPair::loop_recv_mesg(std::function<void(uint8_t *, uint32_t)> callback)
{
    uint8_t *buf;
    int buf_len;
    int ret;

    nn_pollfd pfd;
    pfd.fd = m_sockFd;
    pfd.events = NN_POLLIN;
    int timeout = 3000;  // ms

    if (-1 >= m_sockFd) {
        LOG_ERROR("sock fd not init.\n");
        exit(EXIT_FAILURE);
    }

    m_loop_run = true;
    while (true == m_loop_run) {
        ret = nn_poll(&pfd, 1, timeout);
        if (ret <= 0) {
            // LOG_DEBUG("nn_poll timeout.");
            continue;
        }

        if (pfd.revents & NN_POLLIN) {
            buf_len = nn_recv(m_sockFd, &buf, NN_MSG, NN_DONTWAIT);
            if (buf_len >= 0) {
                callback(buf, buf_len);
                nn_freemsg(buf);
            }
            else {
                LOG_DEBUG("nn_recv nullptr.");
            }
        }
    }
    
    return 0;
}
